/*    file: HKG722.cpp
 *    desc:
 * 
 * created: 2017-05-05
 *  author: chuanjiang.zh@qq.com
 * company: 
 */

#include "HKG722.h"
#include <algorithm>
#include <assert.h>


void HKG722Decoder::init()
{
	NET_DVR_Init();
}

void HKG722Decoder::quit()
{
	NET_DVR_Cleanup();
}

HKG722Decoder::HKG722Decoder():
	m_handle()
{
	m_buffer.ensure(PACKET_SIZE * 2);
}

HKG722Decoder::~HKG722Decoder()
{
	close();
}

bool HKG722Decoder::open()
{
	m_handle = NET_DVR_InitG722Decoder(16000);
	return (m_handle != NULL);
}

void HKG722Decoder::close()
{
	if (m_handle)
	{
		NET_DVR_ReleaseG722Decoder(m_handle);
		m_handle = NULL;
	}

	m_buffer.clear();
}

bool HKG722Decoder::isOpen()
{
	return (m_handle != NULL);
}

int HKG722Decoder::decode(unsigned char* inbuf, int size, unsigned char* outbuf)
{
	int count = flushBuffer(inbuf, size, outbuf);
	outbuf += count;

	while (size >= HKG722Decoder::PACKET_SIZE)
	{
		int length = decodeFrame(inbuf, HKG722Decoder::PACKET_SIZE, outbuf);
		inbuf += HKG722Decoder::PACKET_SIZE;
		size -= HKG722Decoder::PACKET_SIZE;

		outbuf += length;
		count += length;
	}

	if (size > 0)
	{
		assert(size < HKG722Decoder::PACKET_SIZE);
		m_buffer.write(inbuf, size);
	}

	return count;
}

int HKG722Decoder::decodeFrame(unsigned char* inbuf, int size, unsigned char* outbuf)
{
	if (!m_handle)
	{
		return 0;
	}

	if (size != PACKET_SIZE)
	{
		return 0;
	}

	BOOL ret = NET_DVR_DecodeG722Frame(m_handle, inbuf, outbuf);
	return ret ? PCM_SIZE : 0;
}

int HKG722Decoder::flushBuffer(unsigned char*& inbuf, int& size, unsigned char* outbuf)
{
	if (m_buffer.size() == 0)
	{
		return 0;
	}

	if (size <= 0)
	{
		return 0;
	}

	int wanted = HKG722Decoder::PACKET_SIZE - (int)m_buffer.size();
	int length = std::min(wanted, size);
	m_buffer.write(inbuf, length);
	inbuf += length;
	size -= length;

	int outsize = 0;
	if (m_buffer.size() == HKG722Decoder::PACKET_SIZE)
	{
		outsize = decodeFrame(m_buffer.data(), m_buffer.size(), outbuf);
		m_buffer.clear();
	}
	return outsize;
}













HKG722Encoder::HKG722Encoder():
	m_handle()
{
	m_buffer.ensure(HKG722Decoder::PCM_SIZE * 2);
}

HKG722Encoder::~HKG722Encoder()
{
	close();
}

bool HKG722Encoder::open()
{
	m_handle = NET_DVR_InitG722Encoder();
	return isOpen();
}

void HKG722Encoder::close()
{
	if (m_handle)
	{
		NET_DVR_ReleaseG722Encoder(m_handle);
		m_handle = NULL;
	}

	m_buffer.clear();
}

bool HKG722Encoder::isOpen()
{
	return (m_handle != NULL);
}

int HKG722Encoder::encode(unsigned char* inbuf, int size, unsigned char* outbuf)
{
	int count = flushBuffer(inbuf, size, outbuf);
	outbuf += count;

	while (size >= HKG722Decoder::PCM_SIZE)
	{
		int length = encodeFrame(inbuf, HKG722Decoder::PCM_SIZE, outbuf);
		inbuf += HKG722Decoder::PCM_SIZE;
		size -= HKG722Decoder::PCM_SIZE;

		outbuf += length;
		count += length;
	}

	if (size > 0)
	{
		assert(size < HKG722Decoder::PCM_SIZE);
		m_buffer.write(inbuf, size);
	}

	return count;
}

int HKG722Encoder::encodeFrame(unsigned char* inbuf, int size, unsigned char* outbuf)
{
	if (!m_handle)
	{
		return 0;
	}

	if (size != HKG722Decoder::PCM_SIZE)
	{
		return 0;
	}

	BOOL ret = NET_DVR_EncodeG722Frame(m_handle, inbuf, outbuf);
	return ret ? HKG722Decoder::PACKET_SIZE : 0;
}

int HKG722Encoder::flushBuffer(unsigned char*& inbuf, int& size, unsigned char* outbuf)
{
	if (m_buffer.size() == 0)
	{
		return 0;
	}

	if (size <= 0)
	{
		return 0;
	}

	int wanted = HKG722Decoder::PCM_SIZE - (int)m_buffer.size();
	int length = std::min(wanted, size);
	m_buffer.write(inbuf, length);
	inbuf += length;
	size -= length;

	int outsize = 0;
	if (m_buffer.size() == HKG722Decoder::PCM_SIZE)
	{
		outsize = encodeFrame(m_buffer.data(), m_buffer.size(), outbuf);
		m_buffer.clear();
	}
	return outsize;
}

